Make `HTMLEditor` handle selection ranges which starts from or ends in `<foo inert According to the WPTs and their result in the other browsers, we should: * do not work with a range anchored from a node in an element which has `inert`. * collapse the range first when it ends at a node in an element which has `inert`. See new WPT for the detail. Note that `inert` with `contenteditable` must not be so major cases. Therefore, this patch does not fix the edge cases like the `nsFrameSelection` use cases and replacing `Selection` cases of the other edit commands/operations. Depends on D169037 Differential Revision: https://phabricator.services.mozilla.com/D169743 bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1816039 gecko-commit: e91291cda07a215c99f1b36e8d8d1e28935a0d9e gecko-reviewers: m_kato 
diff --git a/inert/inert-inlines-around-selection-range-in-contenteditable.html b/inert/inert-inlines-around-selection-range-in-contenteditable.html new file mode 100644 index 0000000..ff00e16 --- /dev/null +++ b/inert/inert-inlines-around-selection-range-in-contenteditable.html 
@@ -0,0 +1,94 @@ +<!doctype html> +<html> +<head> +<meta charset="utf-8"> +<title>Delete editable range around elements having inert attribute</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../editing/include/editor-test-utils.js"></script> +<script> +document.addEventListener("DOMContentLoaded", () => { + const editingHost = document.querySelector("div[contenteditable]"); + const utils = new EditorTestUtils(editingHost); + + test(t => { + utils.setupEditingHost(t.name, { selection: "setBaseAndExtent" }); + const initialInnerHTML = editingHost.innerHTML; + document.execCommand("delete"); + const desc = `execCommand("delete") at ${t.name}` + assert_equals( + editingHost.innerHTML, + initialInnerHTML, + `${desc}: <span> content should not be deleted because anchor node of Selection is in the <span inert>` + ); + }, "<span inert>a[bc</span><span>de]f</span>"); + + test(t => { + utils.setupEditingHost(t.name, { selection: "setBaseAndExtent" }); + const initialInnerHTML = editingHost.innerHTML; + document.execCommand("delete"); + const desc = `execCommand("delete") at ${t.name}` + assert_equals( + !!editingHost.querySelector("span[inert]"), + true, + `${desc}: <span inert> should not be deleted` + ); + assert_equals( + editingHost.querySelector("span[inert]").textContent, + "def", + `${desc}: <span inert> content should not be deleted` + ); + assert_not_equals( + editingHost.innerHTML, + initialInnerHTML, + `${desc}: <span> content should be deleted (but how to handle it is not tested here)` + ); + }, "<span>a[bc</span><span inert>de]f</span>"); + + test(t => { + utils.setupEditingHost(t.name, { selection: "setBaseAndExtent-reverse" }); + const initialInnerHTML = editingHost.innerHTML; + document.execCommand("delete"); + const desc = `execCommand("delete") at ${t.name} (selection range direction is inverted)` + assert_equals( + !!editingHost.querySelector("span[inert]"), + true, + `${desc}: <span inert> should not be deleted` + ); + assert_equals( + editingHost.querySelector("span[inert]").textContent, + "def", + `${desc}: <span inert> content should not be deleted` + ); + assert_not_equals( + editingHost.innerHTML, + initialInnerHTML, + `${desc}: <span> content should be deleted (but how to handle it is not tested here)` + ); + }, "<span inert>d[ef</span><span>ab]c</span>"); + + test(t => { + utils.setupEditingHost(t.name, { selection: "setBaseAndExtent-reverse" }); + const initialInnerHTML = editingHost.innerHTML; + document.execCommand("delete"); + const desc = `execCommand("delete") at ${t.name} (selection range direction is inverted)` + assert_equals( + editingHost.innerHTML, + initialInnerHTML, + `${desc}: <span> content should not be deleted because anchor node of Selection is in the <span inert>` + ); + }, "<span>d[ef</span><span inert>ab]c</span>"); + + test(t => { + utils.setupEditingHost(t.name, { selection: "setBaseAndExtent" }); + document.execCommand("delete"); + const desc = `execCommand("delete") at ${t.name}` + assert_equals(editingHost.innerHTML, "af", `${desc}: <span inert> should be deleted`); + }, "a[bc<span inert>XYZ</span>de]f"); +}); +</script> +</head> +<body> +<div contenteditable></div> +</body> +</html>